import json

from django import http
from django.core.paginator import Paginator
from django.shortcuts import render
from django.views import View

from apps.index.utils import get_click_list, get_user_info
from apps.news.models import News, UserCollection, Comment, CommentLike, UserFans
from apps.users.models import User
from utils import constants
from utils.response_code import RET


class NewsDetailView(View):
    def get(self, request, news_id):
        # 1.获取点击排行数据
        click_news_list = get_click_list()
        # 2.判断用户是否登录
        user_info = get_user_info(request)
        # 3.显示新闻详情
        try:
            news = News.objects.get(id=news_id)
            print(news.user)
        except Exception as e:
            print(e)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '查询数据失败'})
        if not news:
            # 返回数据未找到的页面
            return http.JsonResponse({'errno': RET.DATAERR, 'errmsg': '新闻不存在'})

        news.clicks += 1
        # if not news.user:
        #     author = None
        # else:
        #     author = {
        #         "id": news.user.id,
        #         "username": news.user.username,
        #         "avatar_url": news.user.avatar_url if news.user.avatar_url else "",
        #         "mobile": news.user.mobile,
        #         "gender": news.user.gender if news.user.gender else "MAN",
        #         "signature": news.user.signature if news.user.signature else "",
        #         "followers_count": news.user.followers.count(),
        #         "news_count": news.user.news_list.count()
        #     }
        #     print(author['followers_count'])
        news_list = {
            "id": news.id,
            "title": news.title,
            "source": news.source,
            "digest": news.digest,
            "create_time": news.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "content": news.content,
            "comments_count": news.comments.count(),
            "clicks": news.clicks,
            "category": news.category,
            "index_image_url": news.index_image_url,
            "author": news.user if news.user else None
        }
        # 4.判断用户是否收藏
        # 设置变量 表示是否收藏 默认为false
        is_collected = False
        if request.user.is_authenticated():
            # 如果当前在用户的收藏列表里 设置is_collected True
            try:
                if UserCollection.objects.get(user=request.user, news=news):
                    is_collected = True
            except Exception as e:
                print(e)
        # 5.评论
        comments = []  # 存放评论对象的列表
        try:
            comments = Comment.objects.filter(news_id=news_id).order_by('-create_time').all()
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '查询数据失败'})
        # 6点赞数据
        comment_like_ids = []
        if request.user.is_authenticated():
            try:
                if len(comments) > 0:
                    # 获取用户所有的在当前新闻的所有评论中点过的赞
                    comment_likes = CommentLike.objects.filter(comment__in=comments,
                                                               user=request.user)
                    # 获取刚才的赞的评论的id
                    if comment_likes:
                        comment_like_ids = [comment_like.comment.id for comment_like in comment_likes]
            except Exception as e:
                print(e)
                return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '获取点赞数据失败'})

        comments_list = []  # 存放评论字典信息的列表
        for comment in comments:
            comment_dict = {
                "id": comment.id,
                "create_time": comment.create_time,
                "content": comment.content,
                "parent": comment.parent,
                "user": comment.user.to_dict(),
                "news_id": comment.news_id,
                "like_count": comment.like_count,
            }
            comment_dict['is_like'] = False
            # 如果评论是用户点过赞的评论 就设置为True
            if request.user.is_authenticated() and comment.id in comment_like_ids:
                comment_dict['is_like'] = True
            comments_list.append(comment_dict)
        # 当前登录用户是否关注当前新闻作者
        is_followed = False
        # 判断用户是否收藏过该新闻
        is_collected = False
        if request.user.is_authenticated():
            try:
                collect = UserCollection.objects.get(news=news, user=request.user)
                followed_flag = UserFans.objects.get(follow=news.user, fans=request.user)
            except Exception as e:
                print(e)
            else:
                if collect:
                    is_collected = True
                if followed_flag:
                    is_followed = True
        context = {
            'data': {
                'user_info': user_info,
                "click_news_list": click_news_list,
                "news": news_list,
                "is_collected": is_collected,
                "comments": comments_list,
                "is_followed": is_followed,
            }
        }
        return render(request, 'base_detail.html', context=context)


class NewsCollectionView(View):
    def post(self, request):
        # 判断用户是否登录
        user_info = get_user_info(request)
        # 11获取传来的json数据
        json_data = json.loads(request.body.decode())
        news_id = json_data.get('news_id')
        action = json_data.get('action')

        # 2校验
        if not user_info:
            return http.JsonResponse({'errno': RET.SESSIONERR, 'errmsg': "用户未登录"})

        if not news_id:
            return http.HttpResponseBadRequest(errno=RET.PARAMERR, errmsg="参数错误")

        if action not in ("collect", "cancel_collect"):
            return http.HttpResponseBadRequest(errno=RET.PARAMERR, errmsg="参数错误")

        # 3查询新闻数据
        try:
            news = News.objects.get(id=news_id)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "查询数据失败"})

        if not news:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': "数据不存在"})

        # 4收藏或者取消收藏
        if action == "collect":
            UserCollection.objects.create(user=request.user, news=news)
        else:
            UserCollection.objects.get(user=request.user, news=news).delete()
        return http.JsonResponse({'errno': RET.OK, 'errmsg': "操作成功"})


class NewsCommentView(View):
    def post(self, request):
        if not request.user.is_authenticated:
            return http.JsonResponse({'errno': RET.SESSIONERR, 'errmsg': "用户未登录"})
            # 获取参数
        data_dict = json.loads(request.body.decode())
        news_id = data_dict.get("news_id")  # 当前的新闻id
        comment_str = data_dict.get("comment")  # 评论的内容
        parent_id = data_dict.get("parent_id")  # 被评论的评论id
        if not all([news_id, comment_str]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数不足"})

        try:
            news = News.objects.get(id=news_id)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "查询数据失败"})

        if not news:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': "该新闻不存在"})

        # 保存到数据库
        try:
            # 初始化评论对象，保存数据
            comment = Comment.objects.create(user=request.user, news_id=news_id, content=comment_str)
            # 如果parent_id存在 说明是对评论的回复
            if parent_id:
                try:
                    parent_comment = Comment.objects.get(id=parent_id)
                    comment.parent = parent_comment
                    comment.save()
                except Exception as e:
                    return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "回复评论id"})
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "保存评论数据失败"})
        data = {
            "id": comment.id,
            "create_time": comment.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            "content": comment.content,
            "parent": comment.parent.to_dict() if comment.parent else None,
            "user": get_user_info(request),
            "news_id": comment.news_id,
            "like_count": comment.like_count,
        }
        data = json.dumps(data)
        # 返回响应
        return http.JsonResponse({'errno': RET.OK, 'errmsg': "评论成功", 'data': data})


class CommentLikeView(View):
    def post(self, request):
        if not request.user.is_authenticated():
            return http.JsonResponse({'errno': RET.SESSIONERR, 'errmsg': "用户未登录"})

        # 获取参数
        json_dict = json.loads(request.body.decode())
        comment_id = json_dict.get("comment_id")
        news_id = json_dict.get("news_id")
        action = json_dict.get("action")

        # 判断参数
        if not all([comment_id, news_id, action]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数错误"})

        if action not in ("add", "remove"):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数错误"})

        # 查询评论数据
        try:
            comment = Comment.objects.get(id=comment_id)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "查询数据失败"})

        if not comment:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': "评论数据不存在"})
        try:
            if action == "add":
                try:
                    comment_like = CommentLike.objects.get(comment=comment, user=request.user)

                except CommentLike.DoesNotExist:
                    comment_like = CommentLike.objects.create(comment=comment, user=request.user)
                    # 增加点赞条数
                    comment.like_count += 1
                    comment.save()
            else:
                # 删除点赞数据
                comment_like = CommentLike.objects.get(comment=comment, user=request.user).delete()
                if comment_like:
                    # 减小点赞条数
                    comment.like_count -= 1
        except Exception as e:
            print(e)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "操作失败"})
        return http.JsonResponse({'errno': RET.OK, 'errmsg': "操作成功"})


class FollowUserView(View):
    def post(self, request):
        """关注/取消关注用户"""
        if not request.user.is_authenticated():
            return http.JsonResponse({'errno': RET.SESSIONERR, 'errmsg': "用户未登录"})
        json_dict = json.loads(request.body.decode())
        user_id = json_dict.get("user_id")
        action = json_dict.get("action")
        if not all([user_id, action]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数错误"})

        if action not in ("follow", "unfollow"):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数错误"})
        # 查询到要关注的用户信息
        try:
            target_user = User.objects.get(id=user_id)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "查询数据库失败"})

        # 要关注的用户是否存在
        if not target_user:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': "未查询到用户数据"})

        # 根据不同操作做不同逻辑
        if action == "follow":
            try:
                UserFans.objects.get(fans=request.user, follow=target_user)
            except UserFans.DoesNotExist:
                # 把当前登录用户添加到目标用户的关注列表中
                try:
                    UserFans.objects.create(fans=request.user, follow=target_user)
                except Exception as e:
                    return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "关注失败"})
            else:
                return http.JsonResponse({'errno': RET.DATAEXIST, 'errmsg': "当前已关注"})
        else:
            try:
                UserFans.objects.get(fans=request.user, follow=target_user).delete()
            except UserFans.DoesNotExist:
                # 取消关注
                return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "取消关注失败"})

        return http.JsonResponse({'errno': RET.OK, 'errmsg': "操作成功"})


class OtherInfoView(View):
    def get(self, request):
        # 获取其他用户id
        user_id = request.GET.get("id")
        if not user_id:
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '参数有误'})
        # 查询用户模型
        other = None
        try:
            other = User.objects.get(id=user_id)
        except Exception as e:
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '查询数据失败'})
        if not other:
            return http.JsonResponse({'errno': RET.USERERR, 'errmsg': '没有此用户'})

        # 判断当前登录用户是否关注过该用户
        is_followed = False
        if request.user.is_authenticated():
            try:
                UserFans.objects.get(follow=other, fans=request.user)
                is_followed = True
            except Exception as e:
                print(e)
        user_info = {
            "id": request.user.id,
            "username": request.user.username,
            "avatar_url": constants.QINIU_DOMIN_PREFIX + request.user.avatar_url if request.user.avatar_url else "",
            "mobile": request.user.mobile,
            "gender": 'WOMAN' if request.user.gender == 1 else "MAN",
            "signature": request.user.signature if request.user.signature else "",
            "followers_count": request.user.followers.count(),
            "news_count": request.user.news_list.count()
        }
        other_info = {
            "id": other.id,
            "username": other.username,
            "avatar_url": constants.QINIU_DOMIN_PREFIX + other.avatar_url if other.avatar_url else "",
            "mobile": other.mobile,
            "gender": 'WOMAN' if other.gender == 1 else "MAN",
            "signature": other.signature if other.signature else "",
            "followers_count": other.followers.count(),
            "news_count": other.news_list.count()
        }
        # 组织数据，并返回
        context = {'data': {
            "user_info": user_info,
            "other_info": other_info,
            "is_followed": is_followed
        }}

        return render(request, 'other.html', context=context)


class OtherNewsView(View):
    def get(self, request):
        # 获取页数
        p = request.GET.get("p", 1)
        user_id = request.GET.get("user_id")
        try:
            p = int(p)
        except Exception as e:
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数错误"})

        if not all([p, user_id]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': "参数错误"})

        try:
            user = User.objects.get(id=user_id)
        except Exception as e:
            print(111)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "数据查询错误"})

        if not user:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': "用户不存在"})

        try:
            news = News.objects.filter(user_id=request.user.id)
            paginate = Paginator(news, constants.OTHER_NEWS_PAGE_MAX_COUNT)
            # 获取当前页数据
            news_li = paginate.page(p)
            # 获取当前页
            current_page = p
            # 获取总页数
            total_page = paginate.num_pages
        except Exception as e:
            print(222)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "数据查询错误"})

        news_dict_li = []
        # 获取新闻的字典数据
        for news_item in news_li:
            news_dict_li.append({
                "id": news_item.id,
                "title": news_item.title,
                "create_time": news_item.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "status": news_item.status,
                "reason": news_item.reason if news_item.reason else ""
            })
        data = {"news_list": news_dict_li, "total_page": total_page, "current_page": current_page}
        return http.JsonResponse({'errno': RET.OK, 'errmsg': "OK", 'data': data})
